//------------------------------------------------------------------------------------------
//	Copyright and Disclaimer Notice
//
//	Copyright (c) 2013 A.C. Verbeck
//
//	This file is part of dsp_lab: A DSP laboratory
//
//	dsp_lab is free software: you can redistribute it and/or modify
//	it under the terms of the GNU General Public License as published by
//	the Free Software Foundation, either version 3 of the License, or
//	(at your option) any later version.
//
//	dsp_lab is distributed in the hope that it will be useful,
//	but WITHOUT ANY WARRANTY; without even the implied warranty of
//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//	GNU General Public License for more details.
//
//	You should have received a copy of the GNU General Public License
//	along with dsp_lab.  If not, see <http://www.gnu.org/licenses/>.
//
//------------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------------
//  The mk_waves utility builds a series of raw waves used in the various synthesis modes.
//	It also builds the same wave as a "wav" file that can be easily imported
//	and played by many different programs.
//------------------------------------------------------------------------------------------

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>

#define LENGTH 256

#define PI	3.14159265358979323846
#define TAU	6.283185307179586476925286766559

//------------------------------------------------------------------------------------------
//  Wave entry structure declaration, function definitions and
//	wv_info structure implementation.
//	Currently, the wave is generated by loading a clean buffer with the wave file.
//	In future, if the buffer cleaning isn't done, then the waves will be additive.
//------------------------------------------------------------------------------------------
typedef struct wv_entry_tag {
	char*	wave_name;
	char*	file_name;
	void	(*fn)(int16_t* buff);
} WV_ENTRY;

void	wv_halfwave(int16_t* buff);
void	wv_sinewave(int16_t* buff);
void	wv_sineblnk(int16_t* buff);
void	wv_fwavblnk(int16_t* buff);
void	wv_snglpeak(int16_t* buff);
void	wv_twopeaks(int16_t* buff);
void	wv_peksblnk(int16_t* buff);
void	wv_ppksblnk(int16_t* buff);
void	wv_impuls10(int16_t* buff);
void	wv_impuls20(int16_t* buff);
void	wv_impuls40(int16_t* buff);

static WV_ENTRY	wv_info[] = {
	{ "+half-sine+blank",	"halfwave.raw",		wv_halfwave	},
	{ "full-sine",			"sinewave.raw",		wv_sinewave	},
	{ "full-sine+blank",	"sineblnk.raw",		wv_sineblnk },
	{ "+two-sine+blank",	"fwavblnk.raw",		wv_fwavblnk },
	{ "single peak+blank",	"snglpeak.raw",		wv_snglpeak },
	{ "full-peak",			"twopeaks.raw",		wv_twopeaks },
	{ "full-peak+blank",	"peksblnk.raw",		wv_peksblnk },
	{ "+half-peak+blank",	"ppksblnk.raw",		wv_ppksblnk },
	{ "impulse 10pt",		"impuls10.raw",		wv_impuls10 },
	{ "impulse 20pt",		"impuls20.raw",		wv_impuls20 },
	{ "impulse 40pt",		"impuls40.raw",		wv_impuls40 }
};

//------------------------------------------------------------------------------------------
//	Main application
//------------------------------------------------------------------------------------------
int main()
{
	int i;
	int16_t data[LENGTH + 2];
	FILE *fd;

	for (i=0; i<11; i++) {
		printf("Wave: %s\n", wv_info[i].wave_name);
		memset(data, 0, sizeof(int16_t)*256);
		fd = fopen(wv_info[i].file_name,"wb");
		(*wv_info[i].fn)(data);
		fwrite(&data,2,LENGTH,fd);
		fclose(fd);
	}
}

//------------------------------------------------------------------------------------------
//	Waveform: Half Wave
//	QI:		sine wave (quadrant 1)
//	QII:	sine wave (quadrant 2)
//	QIII:	silence
//	QIV:	silence
//	Notes: this wave is the first half of a sine wave: 0 to pi
//------------------------------------------------------------------------------------------
void wv_halfwave(int16_t* buff)
{
	for (uint16_t i=0; i<LENGTH/2; i++)
		buff[i] = 32767 * sin(i * 2 * PI / (double) LENGTH);
}

//------------------------------------------------------------------------------------------
//	Waveform: Sine Wave
//	Notes: this wave is a sine wave from 0 to tau (2pi)
//------------------------------------------------------------------------------------------
void wv_sinewave(int16_t* buff)
{
	for (uint16_t i=0; i<LENGTH; i++)
		buff[i] = 32767 * sin(i * 2 * PI / (double) LENGTH);
}

//------------------------------------------------------------------------------------------
//	Waveform: Sine Wave
//	QI:		sine wave (0 to pi)
//	QII:	sine wave (pi to 2pi)
//	QIII:	silence
//	QIV:	silence
//	Notes:	This wave is a sine wave from 0 to tau (2pi).
//			It uses only 1/2 of the buffer
//------------------------------------------------------------------------------------------
void wv_sineblnk(int16_t* buff)
{
	for (uint16_t i=0; i<LENGTH/2; i++)
		buff[i] = 32767 * sin(i * 4 * PI / (double) LENGTH);
}

//------------------------------------------------------------------------------------------
//	Waveform: Sine Wave
//	QI:		sine wave (0 to pi)
//	QII:	sine wave (0 to pi)
//	QIII:	silence
//	QIV:	silence
//	Notes:	This wave is a sine wave from 0 to pi
//			It is duplicated twice.
//			It is 1/2 wave rectified.
//------------------------------------------------------------------------------------------
void wv_fwavblnk(int16_t* buff)
{
	for (uint16_t i=0; i<LENGTH/2; i++)
		buff[i] = abs(32767 * sin(i * 4 * PI / (double) LENGTH));
}

void wv_snglpeak(int16_t* buff)
{
	for (uint16_t i=0; i<=LENGTH/4; i++)
		buff[i] = 32767 * (1.0 - cos(i * 2 * PI / (double) LENGTH));
	for (uint16_t i=0; i<=LENGTH/4; i++)
		buff[LENGTH/2-i] = buff[i];
}

void wv_twopeaks(int16_t* buff)
{
	for (uint16_t i=0; i<=LENGTH/4; i++)
		buff[i] = 32767 * (1.0 - cos(i * 2 * PI / (double) LENGTH));
	for (uint16_t i=0; i<=LENGTH/4; i++)
		buff[LENGTH/2-i] = buff[i];
	for (uint16_t i=0; i<=LENGTH/2; i++)
		buff[LENGTH/2+i] = -buff[i];
}

void wv_peksblnk(int16_t* buff)
{
	for (uint16_t i=0; i<=LENGTH/8; i++)
		buff[i] = 32767 * (1.0 - cos(i * 4 * PI / (double) LENGTH));
	for (uint16_t i=0; i<=LENGTH/8; i++)
		buff[LENGTH/4-i] = buff[i];
	for (uint16_t i=0; i<=LENGTH/4; i++)
		buff[LENGTH/4+i] = -buff[i];
}

void wv_ppksblnk(int16_t* buff)
{
	for (uint16_t i=0; i<=LENGTH/8; i++)
		buff[i] = 32767 * (1.0 - cos(i * 4 * PI / (double) LENGTH));
	for (uint16_t i=0; i<=LENGTH/8; i++)
		buff[LENGTH/4-i] = buff[i];
	for (uint16_t i=0; i<=LENGTH/4; i++)
		buff[LENGTH/4+i] = buff[i];
}

void wv_impuls10(int16_t* buff)
{
	for (uint16_t i=0; i<LENGTH; i++) {
		double temp = 0.0;
		for (uint16_t j=1; j<=10; j++)
			temp += cos(i * j * 2 * PI / (double) LENGTH);
		buff[i] = 32767 / 10.0 * temp;
	}
}

void wv_impuls20(int16_t* buff)
{
	for (uint16_t i=0; i<LENGTH; i++) {
		double temp = 0.0;
		for (uint16_t j=1; j<=20; j++)
			temp += cos(i * j * 2 * PI / (double) LENGTH);
		buff[i] = 32767 / 20.0 * temp;
	}
}

void wv_impuls40(int16_t* buff)
{
	for (uint16_t i=0; i<LENGTH; i++) {
		double temp = 0.0;
		for (uint16_t j=1; j<=40; j++)
			temp += cos(i * j * 2 * PI / (double) LENGTH);
		buff[i] = 32767 / 40.0 * temp;
	}
}

